package com.googlecode.thriftbenchmark.rpc;

import org.apache.thrift.TException;
import org.apache.thrift.TProcessor;
import org.apache.thrift.protocol.TProtocolFactory;
import org.apache.thrift.server.THsHaServer;
import org.apache.thrift.server.TNonblockingServer;
import org.apache.thrift.server.TServer;
import org.apache.thrift.server.TSimpleServer;
import org.apache.thrift.server.TThreadPoolServer;
import org.apache.thrift.transport.TNonblockingServerSocket;
import org.apache.thrift.transport.TNonblockingServerTransport;
import org.apache.thrift.transport.TServerSocket;
import org.apache.thrift.transport.TServerTransport;

import com.googlecode.thriftbenchmark.twitter.TwitterService;
import com.googlecode.thriftbenchmark.twitter.TwitterService.Iface;
import com.googlecode.thriftbenchmark.twitter.TwitterServiceImpl;

/**
 * @author Li Weibo (weibo.leo@gmail.com) //I believe spring-brother
 * @since 2011-12-25 下午03:59:00
 */
public class ServerMain {

    public static void main(String[] args) {
        
        if (args.length != 3) {
            System.err.println("Usage java " + ServerMain.class.getName() + " server_type protocol port");
            return;
        }

        ServerMain app = new ServerMain();
        
        String serverType = args[0];
        String protocol = args[1];
        int port = Integer.parseInt(args[2]);

        try {
            TProcessor processor = new TwitterService.Processor<Iface>(new TwitterServiceImpl());
            
            SimpleTProtocolFactory protocFact = new SimpleTProtocolFactory(protocol);
            TServer server = null;
            if ("ss".equals(serverType)) {
                server = app.getSimpleServer(processor, protocFact, port);
            } else if ("tp".equals(serverType)) {
                server = app.getThreadPoolServer(processor, protocFact, port);
            } else if ("nio".equals(serverType)) {
                server = app.getNonBlockingServer(processor, protocFact, port);
            } else if ("hsha".equals(serverType)) {
                server = app.getHsHaServer(processor, protocFact, port);
            } else {
                
                System.err.println("Invalid server type: " + serverType);
                System.err.println("Please use one of the following types: ");
                System.err.println("ss\tSingle thread socket server");
                System.err.println("tp\tThread pool socket server");
                System.err.println("nio\tNon-blocking single thread server");
                System.err.println("hsha\tHsHa server");
                return;
            }
            System.out.println("starting " + serverType + " server at port " + port  + ", using " + protocol + " protocol");
            server.serve();
        } catch (Throwable e) {
            e.printStackTrace();;
        }
    }
    
    private TServer getHsHaServer(TProcessor processor, TProtocolFactory protocFact, int port)
            throws TException {
        TNonblockingServerTransport serverTransport = new TNonblockingServerSocket(port);
        TServer server = new THsHaServer(new THsHaServer.Args(serverTransport)
                .protocolFactory(protocFact).processor(processor).workerThreads(1024));
        return server;
    }
    
    private TServer getNonBlockingServer(TProcessor processor, TProtocolFactory protocFact, int port)
            throws TException {
        TNonblockingServerTransport serverTransport = new TNonblockingServerSocket(port);
        TServer server = new TNonblockingServer(new TNonblockingServer.Args(serverTransport)
                .protocolFactory(protocFact).processor(processor));
        return server;
    }
    
    private TServer getThreadPoolServer(TProcessor processor, TProtocolFactory protocFact, int port)
            throws TException {
        TServerTransport serverTransport = new TServerSocket(port);
        TServer server = new TThreadPoolServer(new TThreadPoolServer.Args(serverTransport).protocolFactory(
                protocFact).processor(processor).minWorkerThreads(5).maxWorkerThreads(1024));
        return server;
    }
    
    private TServer getSimpleServer(TProcessor processor, TProtocolFactory protocFact, int port)
            throws TException {
        TServerTransport serverTransport = new TServerSocket(port);
        TServer server = new TSimpleServer(new TSimpleServer.Args(serverTransport).protocolFactory(
                protocFact).processor(processor));
        return server;
    }
    
    public void doService(TProcessor processor) {
        try {
            TServerTransport serverTransport = new TServerSocket(9090);
            //TServer server = new TSimpleServer(new Args(serverTransport).processor(processor));
            TServer server = new TThreadPoolServer(
                    new TThreadPoolServer.Args(serverTransport).processor(processor));
            // Use this for a multithreaded server
            // TServer server = new TThreadPoolServer(new TThreadPoolServer.Args(serverTransport).processor(processor));

            System.out.println("Starting the simple server...");
            server.serve();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
